package com.monkeyboy.search.lucene;

import java.io.IOException;
import java.nio.file.Paths;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

/**
 * @author Gavin<br>
 *         多条件查询（标题和内容都包含关键字）
 */
public class MultiQueryParse {
	public static void main(String[] args) {
		// addIndex();
		searchIndex();
	}

	private static void searchIndex() {
		// TODO Auto-generated method stub
		try {
			Directory directory = FSDirectory.open(Paths.get("F:\\lucene_db\\article_tb"));
			// IndexReader：DirectoryReader的open方法指定需要读取的索引库信息，并返回IndexReader实例
			IndexReader indexReader = DirectoryReader.open(directory);
			// IndexSearcher：该实例用于全文检索
			IndexSearcher indexSearcher = new IndexSearcher(indexReader);
			// 创建一个智能分词器
			Analyzer analyzer = new SmartChineseAnalyzer();
			// 创建QueryParse实例，通过QueryParser可以指定需要查询的字段以及分词器信息
			QueryParser queryParse = new MultiFieldQueryParser(new String[] { "title", "content" }, analyzer);// 查询content字段
			// 通过QueryParser 得到query实例，并指定查询的关键字
			Query query = queryParse.parse("深圳");
			// 查询数据，最终数据都封装在TopDocs的实例中（是从索引库中查询数据）
			TopDocs topDocs = indexSearcher.search(query, 10);
			// 通过topDocs获取全部比配记录
			ScoreDoc[] scoreDocs = topDocs.scoreDocs;
			System.err.println("获取到的记录：" + scoreDocs.length);
			for (int i = 0; i < scoreDocs.length; i++) {
				// 获取记录的id（从索引库中获取）
				int id = scoreDocs[i].doc;
				// 文章的得分，匹配度越高分越高
				float score = scoreDocs[i].score;
				System.out.println("文章的得分：" + score);
				System.out.println("id: " + id);
				// 查询数据表（从数据表中查询）
				Document document = indexSearcher.doc(id);
				String articleId = document.get("articleId");
				String title = document.get("title");
				String content = document.get("content");
				System.out.println("articleId: " + articleId + " title:" + title + " content:" + content);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	private static void addIndex() {
		// TODO Auto-generated method stub
		try {
			/**
			 * 指定索引库的文件目录，用FSDirectory文件类型的目录（常用），还要一个是内存型的目录</br>
			 * lucene_db:索引库，相当与mysql中的数据库<br>
			 * article_tb:相当于数据库中的某一个表
			 */
			Directory directory = FSDirectory.open(Paths.get("F:\\lucene_db\\article_tb"));

			// 采用智能分词器
			Analyzer analyzer = new SmartChineseAnalyzer();
			// 创建一个IndexWriter的配置对象，用来指定创建索引的相关信息，比如指定分词器
			IndexWriterConfig config = new IndexWriterConfig(analyzer);
			// 指定索引的创建方式，如果有索引就APPEND，如果没有就CREATE
			config.setOpenMode(OpenMode.CREATE_OR_APPEND);

			// IndexWriter:创建索引， 更新索引，删除索引的操作对象
			IndexWriter indexWriter = new IndexWriter(directory, config);

			// 一个Document实例代表一条记录，相当于数据库中的一条记录
			Document document = new Document();
			/**
			 * 参数1：域名，相当于数据库表中的列名<br>
			 * 参数2：域值，相当于表中列名对应的值<br>
			 * 
			 * note:<br>
			 * StringField不会对关键字进行分词<br>
			 * Store.YES ,会对数据进行存储并分词，如果为NO则不会对数据进行存储，但是索引还是会创建的（相当于书只有目录，但是目录对应的内容为空）
			 */
			document.add(new StringField("articleId", "0002", Store.YES));
			document.add(new TextField("title", "好玩的地方", Store.YES));
			document.add(new TextField("content", "深圳欢乐谷，世界之窗，东门老街，红树林，锦绣中华，小梅沙，梧桐山", Store.YES));

			// 通过indexWriter把数据写进索引库
			indexWriter.addDocument(document);
			// 进行事务的提交
			indexWriter.commit();
			// 关闭IO流，（底层原理就是通过IO流来进行读取和写入的）
			indexWriter.close();
			System.err.println("===>索引创建成功。");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
